home *** CD-ROM | disk | FTP | other *** search
/ PC World Interactive 7 / PC World Interactive 7.iso / program / cprog.EXE / CC_1.ZIP / STDIO.C < prev    next >
Text File  |  1980-01-10  |  8KB  |  336 lines

  1. /*
  2. ** stdio.c -- standard I/O library
  3. **
  4. ** Rewritten by D. R. Hicks -- October 1983
  5. **
  6. ** These functions have been modeled after the UNIX interfaces
  7. ** as described in "The UNIX System" by S. R. Bourne.  Unfortunately
  8. ** my lack of hands-on experience with UNIX will no doubt cause me to
  9. ** misinterpret some details.
  10. */
  11. #define NOCCARGC /* don't pass argument count to functions */
  12.                  /* called by these functions */
  13.  
  14. #define FILE           int     /* mimic standard C file pointers */
  15.  
  16. #define NUMFILES       20      /* maximum number of base I/O files */
  17. #define _NFILE         20      /* maximum number of stream I/O files */
  18. #define _BUFSIZE       512     /* size of stream I/O buffers */
  19. #define PMODE          0       /* file creation options */
  20.  
  21. #include "errno.h"
  22.  
  23.  
  24. /*
  25. ** externs
  26. */
  27. extern int
  28.   fputs(),
  29.   getparm(),
  30.   _doschar(),
  31.   _dosfcall(),
  32.   _dosfxcall();
  33.  
  34.  
  35. /*
  36. ** control variables for stack, heaps, etc
  37. */
  38. int
  39.   _dataseg, /* DS segment reg value */
  40.   _stattop, /* top of statics (in paragraphs) */
  41.   *_heapbase, /* bottom of heap (and top of static storage -- in bytes) */
  42.   *_heapfree, /* first possible free space entry -- address rel to DS */
  43.   *_heaptop, /* current top of heap -- address rel to DS */
  44.   _stkbase,  /* highest (almost) stack offset -- set SP here prior to _EXIT */
  45.   _buffbot, /* bottom of buffer heap (in paragraphs) */
  46.   _buff,    /* buffer heap anchor */
  47.   _bufftop; /* top of buffer heap area (in paragraphs) */
  48.  
  49.  
  50. /*
  51. ** define stream pointers for stdio
  52. */
  53. FILE
  54.   *stdin, /* standard input */
  55.   *stdout, /* standard output */
  56.   *stderr; /* standard error */
  57.  
  58.  
  59. /*
  60. ** UNIX-like error code (see errno.h)
  61. */
  62. #asm /* temp */
  63. Q_ERRNO  LABEL   WORD
  64.          PUBLIC  Q_ERRNO
  65. #endasm
  66. int
  67.   errno;
  68.  
  69. /*
  70. ** arguments, return code, etc for main()
  71. */
  72. static int
  73.   _argc,       /* argument count for main */
  74.   _argv[65],   /* array of character pointers (maximum possible) */
  75.   _mainrc;     /* return code from main */
  76. static char
  77.   _argl[128],  /* argument string copied from PSP (null terminated) */
  78.   *inname,     /* standard in name */
  79.   *outname;     /* standard out name */
  80.  
  81.  
  82. /*
  83. ** recursion flag for exit()
  84. */
  85. static int
  86.   _recur;
  87.  
  88.  
  89. /*
  90. ** user's main entry point
  91. */
  92. extern int
  93.   main();
  94.  
  95. /*
  96. ** link module entry point (from DOS)
  97. */
  98. #define MAIN_ENT _LOGIN /* define label to go on the END statement */
  99. _login() {
  100. #asm
  101.        ASSUME  DS:NOTHING,ES:NOTHING,SS:NOTHING
  102.        MOV     CX,DATASEG
  103.        MOV     ES,CX           ; set up addressability to the data segment
  104.        ASSUME  ES:DATASEG
  105.        MOV     Q_DATASEG,CX    ; save data segment address for others
  106.        MOV     DX,DS           ; save the PSP address
  107.        MOV     Q_BUFFBOT,0     ; above-stack buffer heap does not exist
  108.        MOV     Q_BUFF,0        ; clear buffer heap anchor
  109.        MOV     AX,DS:2         ; get the storage size (in paragraphs)
  110.        MOV     Q_BUFFTOP,AX    ; end of above-stack buffer
  111.        SUB     AX,CX           ; get stack segment size (may be > 64k)
  112.        TEST    AX,0F000H       ; see if > 64k
  113.        JZ      SMALLSTG        ; branch if less than 64k
  114.        MOV     AX,CX           ; stack segment
  115.        ADD     AX,01000H       ; start of buffer heap (skip 16 bytes for luck)
  116.        MOV     Q_BUFFBOT,AX    ; set start of buffer heap
  117.        MOV     AX,0FFFH        ; stack is maximum size
  118. SMALLSTG:
  119.        CLI                     ; be paranoid
  120.        MOV     DS,CX           ; set up data seg reg
  121.        MOV     SS,CX           ; set up stack seg reg
  122.        MOV     CX,4
  123.        SAL     AX,CL           ; calculate stack size in bytes
  124.        MOV     SP,AX           ; set stack pointer
  125.        PUSH    DX              ; save PSP segment address
  126.        MOV     DX,0
  127.        PUSH    DX              ; zero offset to INT 20 in PSP
  128.        MOV     BP,SP           ; set BP to point to stack frame
  129.        MOV     Q_STKBASE,SP    ; save current frame address for _EXIT
  130.        STI                     ; cease paranoia
  131.        ASSUME  SS:DATASEG,ES:DATASEG,DS:DATASEG
  132.        MOV     Q_STATTOP,SEG STACKSEG ; needed to find stack base
  133. #endasm
  134.   _heapbase = (_stattop - _dataseg)<<4; /* first heap byte */
  135.   _heapfree = _heaptop = _heapbase; /* other heap pointers */
  136.   _heapbase[0] = 0; /* size of first entry */
  137.   _heapbase[1] = (-32768); /* mark entry 1st (prior = 0) & free */
  138.   _recur = 0; /* no recursion yet */
  139.   _parms(); /* process command line parameters */
  140.   _iosetup(inname, outname); /* set up standard I/O */
  141.   _mainrc=main(_argc, _argv); /* call the user's main program */
  142.   _ioclnup(); /* close out I/O */
  143.   _exit(_mainrc); /* return with code */
  144.   }
  145.  
  146.  
  147. /*
  148. ** exit with traceback & file clean-up
  149. */
  150. abort(rcode) int rcode; {
  151.   if(_recur) _exit(rcode);
  152.   _recur = 1;
  153.   if(rcode && stderr) {
  154.     fputs("\nabort(", stderr);
  155.     outdec(rcode, stderr);
  156.     fputs(")\n", stderr);
  157.     traceback(stderr);
  158.     }
  159.   _ioclnup();
  160.   _exit(rcode);
  161.   }
  162.  
  163.  
  164. /*
  165. ** exit with file clean-up
  166. */
  167. exit(rcode) int rcode; {
  168.   if(_recur) _exit(rcode);
  169.   _recur = 1;
  170.   _ioclnup();
  171.   _exit(rcode);
  172.   }
  173.  
  174.  
  175. /*
  176. ** exit with no clean-up
  177. */
  178. _exit(rcode) int rcode; {
  179. #asm
  180.        MOV     SP,Q_STKBASE    ; restore stack frame address
  181. ; we might want to add code here to set the DOS return code from [BP]+4
  182. DUMMYP PROC    FAR             ; trick assembler into generating far return
  183.        RET                     ; RET FAR - return to DOS (via INT 20 in PSP)
  184. DUMMYP ENDP
  185. #endasm
  186.   }
  187.  
  188.  
  189. /*
  190. ** display the call sequence
  191. */
  192. traceback(stream) int *stream; {
  193.   int *stack, iar, *bp;
  194.   fputs("\ndata segment address: ", stream);
  195.   outhex(_dataseg, stream);
  196.   fputs("\n", stream);
  197.   stack = &stream;
  198.   stack -= 2;
  199.   while(ult(stack,_stkbase)) {
  200.     bp = *stack++;
  201.     iar = *stack;
  202.     fputs("return address: ", stream);
  203.     outhex(iar, stream);
  204.     fputs("   stack frame address: ", stream);
  205.     outhex(bp, stream);
  206.     fputs("\n", stream);
  207.     if(ult(bp,stack)) break;
  208.     stack = bp;
  209.     }
  210.   }
  211.  
  212.  
  213. /*
  214. ** unsigned less than
  215. */
  216. static ult(a, b) int a, b; {
  217.   if(a>=0)
  218.     if(b>=0)
  219.       return (a<b);
  220.     else
  221.       return 1;
  222.   else
  223.     if(b>=0)
  224.       return 0;
  225.     else
  226.       return (a<b);
  227.   }
  228.  
  229.  
  230. /*
  231. ** output a decimal value
  232. */
  233. static outdec(number, stream) int number, *stream; {
  234.   int k, zs;
  235.   char c;
  236.   zs = 0;
  237.   k = 10000;
  238.   if(number<0) {
  239.     number = (-number);
  240.     fputc('-', stream);
  241.     }
  242.   while(k>=1) {
  243.     c = number/k + '0';
  244.     if((c!='0')|(k==1)|(zs)) {
  245.       zs = 1;
  246.       fputc(c, stream);
  247.       }
  248.     number = number%k;
  249.     k = k/10;
  250.     }
  251.   }
  252.  
  253.  
  254. /*
  255. ** output a hex value
  256. */
  257. static outhex(number, stream) int number, *stream; {
  258.   int k;
  259.   char c;
  260.   k = 4;
  261.   while(k--) {
  262.     c = (number>>12)&15;
  263.     if(c<10) c = c + '0';
  264.     else c = (c-10) + 'A';
  265.     fputc(c, stream);
  266.     number = number<<4;
  267.     }
  268.   }
  269.  
  270.  
  271. /*
  272. ** process command line parms
  273. */
  274. static _parms() {
  275.   int count;
  276.   char *ptr;
  277.   inname = "kbd"; /* set default */
  278.   outname = "scrn"; /* set default */
  279.   count = getparm(_argl); /* get the argument list from the PSP */
  280.   _argc = 1;
  281.   ptr = _argl;
  282.   _argv[0] = "main"; /* default for the first argument
  283.                         (since DOS hides true file name) */
  284.   while(1) {
  285.     while(*ptr == ' ') ptr++;
  286.     if(!*ptr) break;
  287.     if(*ptr == '<') /* if input redirection */
  288.       inname = ++ptr;
  289.     else if(*ptr == '>') /* if output redirection */
  290.       outname = ++ptr;
  291.     else
  292.       _argv[_argc++] = ptr;
  293.     while(*ptr && *ptr != ' ') ++ptr;
  294.     if(!*ptr) break;
  295.     *ptr++ = 0;
  296.     }
  297.   _argv[_argc] = 0;
  298.   }
  299.  
  300. /*
  301. ** set up I/O system
  302. */
  303. _iosetup(inname, outname) char *inname, *outname; {
  304.   _baseinit();
  305.   _strminit(inname, outname, "con");
  306.   }
  307.  
  308.  
  309. /*
  310. ** close files and clean up I/O
  311. */
  312. _ioclnup() {
  313.   _strmclnup();
  314.   _baseclnup();
  315.   }
  316.  
  317. #include <streamio.h>
  318. #include "streamio.c"
  319. #include "sgtty.h"
  320. #include "doscall.h"
  321. #include "baseio1.c"
  322. #include "baseio2.c"
  323. #include "heap.c"
  324.  
  325. /*
  326. ** stack segment to satisfy linker, provide interrupt space while setting up,
  327. ** and to provide a way to identify the top of DATASEG
  328. */
  329. #asm
  330. STACKSEG SEGMENT STACK
  331.        DB 256 DUP(?)
  332. STACKSEG ENDS
  333. #endasm
  334.  
  335.  
  336.